
from rest_framework.views import APIView
from alipay import AliPay
from django.conf import settings
from rest_framework.response import Response
from order.models import Order
from rest_framework import status
from coupon.models import UserCoupon
from django.db import transaction   #事物
from user.models import UserCourse
from course.models import CourseExpire

import logging
log = logging.getLogger("django")

class AlipayAPIView(APIView):

    def get(self,request):
        """
            前端发起请求获取支付宝的支付地址
        """
        #获取订单号
        order_number = request.query_params.get('order_number')
        #判断订单是否存在
        try:
            order = Order.objects.get(order_number=order_number)
        except Order.DoesNotExist:
            return Response({"message":"对不起，订单不存在"},status=status.HTTP_400_BAD_REQUEST)
        #初始化支付对象

        alipay = AliPay(
            appid=settings.ALIPAY_CONFIG["appid"],
            app_notify_url=settings.ALIPAY_CONFIG["app_notify_url"],  # 默认回调url
            app_private_key_path=settings.ALIPAY_CONFIG["app_private_key_path"],
            alipay_public_key_path = settings.ALIPAY_CONFIG["alipay_public_key_path"],
            sign_type=settings.ALIPAY_CONFIG["sign_type"],  # RSA 或者 RSA2
            debug = settings.ALIPAY_CONFIG["debug"],  # 默认False
        )

        #调用接口
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order.order_number,        #必传支付宝的参数
            total_amount=float(order.real_price),              #订单总金额 必传支付宝的参数
            subject=order.order_title,                #订单标题 必传支付宝的参数
            return_url=settings.ALIPAY_CONFIG["return_url"],
            notify_url=settings.ALIPAY_CONFIG["notify_url"]  # 可选, 不填则使用上面实例化调用的app_notify_url
        )

        url = settings.ALIPAY_CONFIG["gateway_url"] + order_string
        return Response(url)

from django.http.response import HttpResponse
class AliPayResultAPIView(APIView):
    def get(self,request):
        """处理支付宝的同步通知结果"""
        # 初始化支付对象
        alipay = AliPay(
            appid=settings.ALIPAY_CONFIG["appid"],
            app_notify_url=settings.ALIPAY_CONFIG["app_notify_url"],  # 默认回调url
            app_private_key_path=settings.ALIPAY_CONFIG["app_private_key_path"],
            alipay_public_key_path=settings.ALIPAY_CONFIG["alipay_public_key_path"],
            sign_type=settings.ALIPAY_CONFIG["sign_type"],  # RSA 或者 RSA2
            debug=settings.ALIPAY_CONFIG["debug"],  # 默认False
        )

        data = request.query_params.dict()
        signature = data.pop("sign")
        success = alipay.verify(data, signature)
        # success 返回False原因不明
        if success is False:
            """
                判断支付成功有多种方法，首先用户支付成功后，会返回url，里面带的参数信息没有trade_status参数(trade_status参数在异步通知中才有)
                所以无法判断，故：
                1，可以根据success直接判断
                2，可以根据支付宝支付返回url中有trade_no，流水号，通过trade_no参数查支付宝接口这个交易是否成功来判断也可以
            """
            return self.change_order_status(data)
        return Response({"message": "当前订单支付失败~"})

    def post(self,request):
        """处理支付宝的异步通知请求"""
        alipay = AliPay(
            appid=settings.ALIPAY_CONFIG["appid"],
            app_notify_url=settings.ALIPAY_CONFIG["app_notify_url"],  # 默认回调url
            app_private_key_path=settings.ALIPAY_CONFIG["app_private_key_path"],
            alipay_public_key_path=settings.ALIPAY_CONFIG["alipay_public_key_path"],
            sign_type=settings.ALIPAY_CONFIG["sign_type"],  # RSA 或者 RSA2
            debug=settings.ALIPAY_CONFIG["debug"],  # 默认False
        )
        data = request.data
        signature = data.pop("sign")
        success = alipay.verify(data, signature)
        if success is False and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED" ):
            response =  self.change_order_status(data)
            if "credit" in response.data:
                return HttpResponse("success")
        return Response({"message": "当前订单支付失败~"})




    def change_order_status(self,data):
        """同步发送通知"""
        order_number = data.get("out_trade_no")
        # 判断订单是否存在
        try:
            order = Order.objects.get(order_number=order_number, order_status=0)
        except Order.DoesNotExist:
            return Response({"message": "支付失败，订单不存在~"}, status=status.HTTP_400_BAD_REQUEST)

        # 启用事物

        with transaction.atomic():
            # 记录回滚点
            save_id = transaction.savepoint()
            try:

                # 需要更新订单状态，记录订单支付时间即可
                from datetime import datetime
                order.pay_time = datetime.now()
                order.order_status = 1  # 1是已支付
                order.save()
                # 如果使用优惠卷或者积分，需要修改优惠卷的使用状态，或者扣除积分
                user_coupon_id = order.coupon
                if user_coupon_id > 0:
                    """使用了优惠卷"""
                    # 查
                    user_coupon = UserCoupon.objects.get(pk=user_coupon_id, is_use=False, is_show=True,
                                                         is_deleted=False)
                    # 改
                    user_coupon.is_use = True
                    user_coupon.save()
                credit = order.credit
                if credit > 0:
                    """使用了积分"""
                    # 查
                    user = order.user
                    # 改
                    user.credit -= credit
                    user.save()

                # 记录用户成功购买的课程，增加课程购买的人数
                order_detail_list = order.order_courses.all()
                course_list = []
                for order_detail in order_detail_list:
                    """循环这个订单中，所有购买的商品"""
                    course = order_detail.course
                    course.students += 1
                    course.save()

                    pay_timestamp = order.pay_time.timestamp()
                    if order_detail.expire > 0:
                        # 有效期内购买
                        expire = CourseExpire.objects.get(pk=order_detail.expire)
                        expire_timestamp = expire.expire_time * 24 * 60 * 60
                        out_time = datetime.fromtimestamp(pay_timestamp + expire_timestamp)
                    else:
                        # 永久购买
                        out_time = None

                    UserCourse.objects.create(
                        user_id=order.user.id,
                        course_id=course.id,
                        trade_no=data.get("trade_no"),
                        buy_type=1,
                        pay_time=order.pay_time,
                        out_time=out_time,
                    )
                    course_list.append({
                        "id":course.id,
                        "name":course.name,
                    })

            except:
                # 回滚
                log.error("订单结果处理故障，无法修改订单相关记录状态")
                transaction.savepoint_rollback(save_id)
                return Response({"message": "对不起，修改订单相关记录失败"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        #返回结果

        return Response({
            "message": "支付成功",
            "credit": order.user.credit,
            "pay_time":order.pay_time,
            "real_price":order.real_price,
            "course_list":course_list,
        })











